home *** CD-ROM | disk | FTP | other *** search
- {NEWSQWK.PAS}
-
- {
- Converts USENET files to QWK format ..
-
- You'll need PKZIP to use this.
-
- I use NXpress for my Newsgroup reader, in it saves it files with an
- extension of .MBX. If you newsreader saves in someother format, then
- change the extension default at the front of the program.
-
- Perhaps you newsreader has a SAVEAS feature that allows you to download
- all of the material and save it as a text file. If so, you could use it.
- Just save the files as SOMEFILE.MBX in the same DIR as this program,
- and it'll create the QWK file for you.
-
- Gayle Davis 05/28/96
-
- }
-
- {$V-,S-,I-}
- {$M 16384,0,655360} { no need to leave memory for PKZIP !!!
- see the EXECUTE procedure below and find out how !!}
-
- USES
- Dos, Crt, Upper, RLine;
- { NOTE : Upper is in STRINGS.SWG
- RLINE is in TEXTFILE.SWG }
-
- CONST
- ControlHdr : ARRAY [1..11] OF STRING [30] = (
-
- {1} 'SOURCEWARE ARCHIVAL GROUP', { change this to whatever you want ! }
- {2} 'Goshen', { ditto }
- {3} '875-8133', { ditto }
- {4} 'Gayle Davis', { ditto }
- {5} '99999,SWAG', { ditto }
- {6} '11-03-1993,04:41:37', { this will get updated automatically }
- {7} 'SWAG Genius', { whatever pleases you ! }
- {8} '', { QMAIL Menu name ??? }
- {9} '0', { allways ZERO ??? }
- {10} '0', { total number of messages in package }
- {11} '0'); { number of conferences-1 here }
- { next is 0 , then first conference }
-
- TYPE
-
- BlockArray = ARRAY [1..128] OF CHAR;
- CharArray = ARRAY [1..6] OF CHAR; { to read in chunks }
- ControlArray = ARRAY [1..100] OF STRING [40]; { set to 100 conferences !!}
- bsingle = array [0..4] of byte;
-
- MSGDATHdr = RECORD
- Status : CHAR;
- MSGNum : ARRAY [1..7] OF CHAR;
- Date : ARRAY [1..8] OF CHAR;
- Time : ARRAY [1..5] OF CHAR;
- UpTO : ARRAY [1..25] OF CHAR;
- UpFROM : ARRAY [1..25] OF CHAR;
- Subject : ARRAY [1..25] OF CHAR;
- PassWord : ARRAY [1..12] OF CHAR;
- ReferNum : ARRAY [1..8] OF CHAR;
- NumChunk : CharArray;
- Alive : BYTE;
- LeastSig : BYTE;
- MostSig : BYTE;
- Reserved : ARRAY [1..3] OF CHAR;
- END;
-
- MBXHeader = RECORD
- Xref : STRING[70];
- Path : STRING;
- From : STRING[70];
- Subject : STRING[70];
- Date : STRING[40];
- Lines : WORD;
- Status : CHAR;
- END;
-
- CONST
-
- PKZIP : PathStr = 'PKZIP.EXE';
- QWKFile : PathStr = 'NEWS.QWK';
-
- VAR
-
- MBXF : TEXT;
- QWKF : FILE;
- ControlF : TEXT;
-
- FOL : FileOfLinesPtr;
- FOLPos : LONGINT;
-
- SavePath,
- SwagPath,
- MBXFn,
- MsgFName : PATHSTR;
-
- TR : SearchRec;
-
- ConfNum,
- Number : WORD; { message number, conference number }
-
- MSGHdr : MSGDatHdr;
- ch : CHAR;
- count : INTEGER;
- chunks : INTEGER;
- ControlVal : ControlArray;
- ControlIdx : BYTE;
- ConfName,
- WStr : STRING;
-
- FUNCTION TrimL (InpStr : STRING) : STRING; ASSEMBLER;
- ASM
- PUSH DS
- LDS SI, InpStr
- XOR AX, AX
- LODSB
- XCHG AX, CX
- LES DI, @Result
- INC DI
- JCXZ @@2
-
- MOV BL, ' '
- CLD
- @@1 : LODSB
- CMP AL, BL
- LOOPE @@1
- DEC SI
- INC CX
- REP MOVSB
-
- @@2 : XCHG AX, DI
- MOV DI, WORD PTR @Result
- SUB AX, DI
- DEC AX
- STOSB
- POP DS
- END;
-
- FUNCTION TrimR (InpStr : STRING) : STRING;
-
- VAR i : INTEGER;
-
- BEGIN
- i := LENGTH (InpStr);
- WHILE (i >= 1) AND (InpStr [i] = ' ') DO
- i := i - 1;
- TrimR := COPY (InpStr, 1, i)
- END;
-
- FUNCTION TrimB (InpStr : STRING) : STRING;
-
- BEGIN
- TrimB := TrimL (TrimR (InpStr) );
- END;
-
- FUNCTION PadR (InpStr : STRING; FieldLen : BYTE) : STRING;
- {-Return a string right-padded to length len with ch}
- VAR
- o : STRING;
- SLen : BYTE ABSOLUTE InpStr;
- BEGIN
- IF LENGTH (InpStr) >= FieldLen THEN
- PadR := COPY (InpStr, 1, FieldLen)
- ELSE BEGIN
- o [0] := CHR (FieldLen);
- MOVE (InpStr [1], o [1], SLen);
- IF SLen < 255 THEN
- FILLCHAR (o [SUCC (SLen) ], FieldLen - SLen, #32);
- PadR := o;
- END;
- END;
-
-
- FUNCTION GoodNumber (S : STRING) : BOOLEAN;
- VAR
- Num : LONGINT;
- Code : WORD;
-
- BEGIN
- Num := 0;
- VAL (S, Num, Code);
- GoodNumber := ( (Code = 0) AND (Num > 0) AND (S > '') );
- END;
-
-
- FUNCTION IntStr (Num : LONGINT; Width : BYTE; Zeros : BOOLEAN) : STRING;
- { Return a string value (width 'w')for the input integer ('n') }
- VAR
- Stg : STRING;
- BEGIN
- STR (Num : Width, Stg);
- IF Zeros THEN BEGIN
- FOR Num := 1 TO Width DO IF Stg [Num] = #32 THEN Stg [Num] := '0';
- END ELSE Stg := TrimL (Stg);
- IntStr := Stg;
- END;
-
- FUNCTION GetStr (VAR InpStr : STRING; Delim : CHAR) : STRING;
-
- VAR i : INTEGER;
- BEGIN
- i := POS (Delim, InpStr);
- IF i = 0 THEN
- BEGIN
- GetStr := InpStr;
- InpStr := ''
- END ELSE
- BEGIN
- GetStr := COPY (InpStr, 1, i - 1);
- DELETE (InpStr, 1, i)
- END
- END;
-
- FUNCTION Str2LongInt (S : STRING; VAR I : LONGINT) : BOOLEAN;
- {-Convert a string to an integer, returning true if successful}
- VAR
- code : WORD;
- BEGIN
- VAL (S, I, code);
- IF code <> 0 THEN BEGIN
- i := 0;
- Str2LongInt := FALSE;
- END ELSE
- Str2LongInt := TRUE;
- END;
-
- FUNCTION GetNumber (VAR InpStr : STRING; Delim : CHAR) : LONGINT;
-
- VAR S, S1 : STRING;
- I : LONGINT;
- BEGIN
- I := 0;
- S1 := InpStr;
- S := GetStr (InpStr, Delim);
- IF NOT GoodNumber (S) THEN InpStr := S1 ELSE
- Str2LongInt (S, I);
- GetNumber := I;
- END;
-
-
- FUNCTION NameOnly (FileName : PathStr) : PathStr;
- { Strip any path information from a file specification }
- VAR
- Dir : DirStr;
- Name : NameStr;
- Ext : ExtStr;
- BEGIN
- FSplit (FileName, Dir, Name, Ext);
- NameOnly := Name;
- END {NameOnly};
-
- FUNCTION SlashDate(AddCentury : BOOLEAN) : STRING; {10/08/88}
-
- VAR
- MonthName, dayname, yearname, dayofweekname : WORD;
-
- BEGIN
-
- GETDATE (yearname, MonthName, dayname, dayofweekname);
-
- IF AddCentury THEN
- SlashDate := IntStr (MonthName, 2, TRUE) + '/' +
- IntStr (dayname, 2, TRUE) + '/' +
- IntStr (yearname, 4, TRUE) ELSE
-
- SlashDate := IntStr (MonthName, 2, TRUE) + '/' +
- IntStr (dayname, 2, TRUE) + '/' +
- COPY (IntStr (yearname, 4, TRUE), 3, 2);
-
- END;
-
- FUNCTION PlainTime : STRING; {09:10:01}
-
- VAR
- Hr, Min, Sec, sec100 : WORD;
-
- BEGIN
- GETTIME (Hr, Min, Sec, sec100);
- PlainTime := IntStr (Hr, 2, TRUE) + ':' +
- IntStr (Min, 2, TRUE) + ':' +
- IntStr (Sec, 2, TRUE);
-
- END;
-
- FUNCTION EraseFile ( S : PathStr ) : BOOLEAN ;
- VAR F : FILE;
- BEGIN
- EraseFile := FALSE;
- ASSIGN (F, S);
- RESET (F);
- IF IORESULT <> 0 THEN EXIT;
- CLOSE (F);
- ERASE (F);
- EraseFile := (IORESULT = 0);
- END;
-
- PROCEDURE ReallocateMemory(P : POINTER); ASSEMBLER;
- ASM
- MOV AX, PrefixSeg
- MOV ES, AX
- MOV BX, WORD PTR P+2
- CMP WORD PTR P,0
- JE @OK
- INC BX
-
- @OK:
- SUB BX, AX
- MOV AH, 4Ah
- INT 21h
- JC @X
- LES DI, P
- MOV WORD PTR HeapEnd,DI
- MOV WORD PTR HeapEnd+2,ES
-
- @X:
- END;
-
- FUNCTION EXECUTE(Name : PathStr ; Tail : STRING) : WORD; ASSEMBLER;
- ASM
- {$IFDEF CPU386}
- DB 66h
- PUSH WORD PTR HeapEnd
- DB 66h
- PUSH WORD PTR Name
- DB 66h
- PUSH WORD PTR Tail
- DB 66h
- PUSH WORD PTR HeapPtr
- {$ELSE}
- PUSH WORD PTR HeapEnd+2
- PUSH WORD PTR HeapEnd
- PUSH WORD PTR Name+2
- PUSH WORD PTR Name
- PUSH WORD PTR Tail+2
- PUSH WORD PTR Tail
- PUSH WORD PTR HeapPtr+2
- PUSH WORD PTR HeapPtr
- {$ENDIF}
- CALL ReallocateMemory
- CALL SwapVectors
- CALL DOS.EXEC
- CALL SwapVectors
- CALL ReallocateMemory
- MOV AX, DosError
- OR AX, AX
- JNZ @OUT
- MOV AH, 4Dh
- INT 21h
-
- @OUT:
- END;
-
-
- PROCEDURE FindPKZip;
- VAR
- S : PathStr;
- BEGIN
- S := FSearch ('PKZIP.EXE', GetEnv ('PATH') );
- IF S = '' THEN
- BEGIN
- WriteLn(#7,'You GOTTA have PKZIP somewhere on your PATH to do this !!');
- HALT(1);
- END;
- PKZIP := FExpand (S);
- END;
-
- PROCEDURE CleanUp;
- { clean up after ourselves }
- BEGIN
- FINDFIRST ('*.NDX', $21, TR);
- WHILE DosError = 0 DO
- BEGIN
- EraseFile(TR.NAME);
- FINDNEXT (TR);
- END;
- EraseFile('MESSAGES.DAT');
- EraseFile('CONTROL.DAT');
-
- END;
-
- PROCEDURE CreateControlDat;
- VAR
- I : BYTE;
- BEGIN
-
- ControlHdr [ 6] := SlashDate(TRUE)+','+PlainTime;
- ControlHdr [10] := IntStr (Count, 5, FALSE);
- ControlHdr [11] := IntStr (PRED (ConfNum), 3, FALSE);
-
- ASSIGN (ControlF, 'CONTROL.DAT');
- REWRITE (ControlF);
- FOR I := 1 TO 11 DO
- WRITELN (ControlF, ControlHdr [i]);
- FOR I := 1 TO ControlIdx DO
- WRITELN (ControlF, ControlVal [i]);
- CLOSE (ControlF);
- END;
-
- PROCEDURE CreateMessageDat;
- VAR
- I : BYTE;
- Buff : BlockArray;
- BEGIN
-
- FILLCHAR (ControlVal, SIZEOF (ControlVal), #0);
- FILLCHAR (Buff, SIZEOF (Buff), #32);
- FILLCHAR (MsgHdr, SIZEOF (MsgHdr), #32);
- ConfNum := 0;
- ControlIdx := 0;
- Number := 0;
- ASSIGN (QWKF, 'MESSAGES.DAT');
- REWRITE (QWKF, SIZEOF (MsgHdr) );
- WStr := 'NEWS TO QWK (c) 1996 GDSOFT';
- FOR I := 1 TO LENGTH (WStr) DO Buff [i] := WSTR [i];
- BLOCKWRITE (QwkF, Buff, 1);
- END;
-
- FUNCTION ArrayTOInteger (B : CharArray; Len : BYTE) : LONGINT;
-
- VAR I : BYTE;
- S : STRING;
- E : INTEGER;
- T : INTEGER;
-
- BEGIN
- S := '';
- FOR I := 1 TO PRED (Len) DO IF B [i] <> #32 THEN S := S + B [i];
- VAL (S, T, E);
- IF E = 0 THEN ArrayToInteger := T;
- END;
-
- PROCEDURE GetNewsGroupHeader(VAR NGH : MBXHeader);
-
- VAR
- Junk : STRING;
-
- BEGIN
- WHILE POS('STATUS:',UpCaseStr(FOL^.LastLine)) = 0 DO
- BEGIN
- FOL^.SeekLine(FOLPos);
- INC(FOLPos);
- IF POS('XREF:',UpCaseStr(FOL^.LastLine)) > 0 THEN
- NGH.XRef := TrimB(COPY(FOL^.LastLine,6,$FF));
- IF POS('PATH:',UpCaseStr(FOL^.Lastline)) > 0 THEN
- NGH.Path := TrimB(COPY(FOL^.LastLine,6,$FF));
- IF POS('FROM:',UpCaseStr(FOL^.Lastline)) > 0 THEN
- NGH.From := TrimB(COPY(FOL^.LastLine,6,$FF));
- IF POS('SUBJECT:',UpCaseStr(FOL^.Lastline)) > 0 THEN
- NGH.Subject := Trimb(COPY(FOL^.LastLine,9,$FF));
- IF POS('DATE:',UpCaseStr(FOL^.Lastline)) > 0 THEN
- NGH.Date := Trimb(COPY(FOL^.LastLine,6,$FF));
- IF POS('LINES:',UpCaseStr(FOL^.Lastline)) > 0 THEN
- BEGIN
- Junk := GetStr(FOL^.LastLine,#32);
- NGH.Lines := GetNumber(FOL^.LastLine,#32);
- END;
- IF POS('STATUS:',UpCaseStr(FOL^.Lastline)) > 0 THEN
- NGH.STATUS := 'S';
- END;
- END;
-
- PROCEDURE ReadMessage(HdrPos : LONGINT);
- VAR
-
- HDR : MsgDatHdr;
- Block : BlockArray;
- EndPos : LONGINT;
- Chunks : LONGINT;
- J,K : INTEGER;
- I,SFOL : LONGINT;
- NS : STRING;
- NGH : MBXHeader;
-
- PROCEDURE MoveDataToBlock (Start, Len : BYTE; S : STRING; VAR Block : BlockArray);
- VAR I, K : BYTE;
-
- BEGIN
- K := 0;
- FOR I := Start TO PRED (Start + Len) DO
- BEGIN
- INC (k);
- Block [i] := S [k];
- END;
- END;
-
-
- PROCEDURE WriteHeader;
- BEGIN
- { write the header out }
- Seek(QwkF,HdrPos);
- FillChar(Block,SizeOf(Block),#32);
- MoveDataToBlock( 2, 7,PadR(IntStr(Number,7,FALSE),7),Block); { number }
- MoveDataToBlock( 9, 8,SlashDate(FALSE),Block); { date }
- MoveDataToBlock( 17, 5,PlainTime,Block); { Time }
- MoveDataToBlock( 22,25,PadR(ControlHdr[4],25),Block); { To }
- MoveDataToBlock( 47,25,PadR(NGH.FROM,25),Block); { From }
- MoveDataToBlock( 72,25,PadR(NGH.Subject,25),Block); { Subj }
- MoveDataToBlock( 97,20,PadR('IMPORT',20),Block); { Confname }
- MoveDataToBlock(117, 6,PadR(IntStr(Chunks,6,FALSE),6),Block); { Numpacs }
- MoveDataToBlock(124, 1,Chr(64),Block);
- BlockWrite(QwkF,Block,1);
- END;
-
- PROCEDURE WriteBlock;
- BEGIN
- BLOCKWRITE (QwkF, Block, 1);
- FILLCHAR (Block, SIZEOF (Block), #32);
- INC (chunks); { increment block count }
- k := 0;
- END;
-
- PROCEDURE ProcessLine;
- VAR
- c : BYTE;
- BEGIN
- FOR c := 1 TO LENGTH(FOL^.LastLine) DO
- BEGIN
- INC (k);
- {
- IF FOL^.LastLine [c] = #13 THEN
- BEGIN
- Block [k] := #227;
- INC (c);
- END ELSE Block [k] := FOL^.LastLine [c];
- }
- Block[k] := FOL^.Lastline[c];
- IF k = 128 THEN WriteBlock;
-
- END; { for }
-
- { write end of line }
- INC(k);
- Block[k] := #227;
- IF k=128 THEN WriteBlock;
- END;
-
- BEGIN
-
- SFOL := SUCC(FOLPos);
-
- { read the header block }
- GetNewsGroupHeader(NGH);
-
- { fill QWK Header with info }
-
- FILLCHAR (Block, SIZEOF (Block), #32);
- FILLCHAR(Hdr,SizeOF(Hdr),#0);
-
- { write the header out }
- chunks := 1; { number packs }
- INC(Number); { update message number }
-
- { write the header to our QWK file }
- WriteHeader;
-
- { write the blocks out }
- K := 0;
- FILLCHAR (Block, SIZEOF (Block), #32);
-
- FOR I := FOLPos TO FOLPos + NGH.Lines DO
- BEGIN
- FOL^.SeekLine(i);
- ProcessLine;
- END;
-
- J := I; { save the FOLPos for later }
-
- { write the original header out }
- FOL^.LastLine := ' ';
- ProcessLine;
- FOL^.LastLine := 'Original Header:';
- ProcessLine;
- FOL^.LastLine := ' ';
- ProcessLine;
-
- FOR I := SFOL TO FOLPos DO
- BEGIN
- FOL^.Seekline(i);
- ProcessLine;
- END;
-
- IF k > 0 THEN WriteBlock;
- FOLPos := j; { update the position in the file }
-
- EndPos := FilePos(QwkF);
-
- { update the header }
- WriteHeader;
- SEEK(QwkF, EndPos);
-
- END;
-
- PROCEDURE ProcessUseNetFile (FN : PathStr);
- { this is the heart !! Read messages from MBX file and save in QWK file }
- VAR
- ndxF : File;
- b : bSingle;
- r : REAL;
- n : LONGINT;
-
- { converts TP real to Microsoft 4 bytes single .. GOOFY !!!! }
- procedure real_to_msb (preal : real; var b : bsingle);
- var
- r : array [0 .. 5] of byte absolute preal;
- begin
- b [3] := r [0];
- move (r [3], b [0], 3);
- end; { procedure real_to_msb }
-
-
- BEGIN
-
- WriteLn('Process .. ',FN);
-
- { create the NDX file }
- ASSIGN (ndxF,IntStr(ConfNum,3,TRUE)+'.NDX');
- REWRITE (ndxF,1);
-
- WHILE (FOLPos < FOL^.Totallines) DO
- BEGIN
-
- n := SUCC(FilePos(QwkF)); { ndx wants the RELATIVE position }
- r := N; { make a REAL }
- REAL_TO_MSB(r,b); { convert to MSB format }
- BLOCKWRITE(ndxF,B,SizeOf(B)); { store it }
-
- WriteLn('Process message .. ',IntStr(Number+1,5,FALSE));
- ReadMessage(PRED(n));
- INC(Count);
- END;
-
- CLOSE (NdxF);
-
- { update the CONTROL file array }
- INC (ControlIdx);
- ControlVal [ControlIdx] := IntStr (ConfNum, 3, TRUE);
- INC (ControlIdx);
- ControlVal [ControlIdx] := ConfName;
- INC (ConfNum);
-
- END;
-
- PROCEDURE GetConferenceName;
-
- VAR
- Junk : STRING;
-
- BEGIN
- WHILE POS('NEWSGROUPS:',UpCaseStr(FOL^.LastLine)) = 0 DO
- BEGIN
- FOL^.SeekLine(FOLPos);
- INC(FOLPos);
- END;
- Junk := GetStr(FOL^.LastLine,' ');
- ConfName := TrimB(FOL^.Lastline);
- FOLPos := 1;
- END;
-
- BEGIN
-
- ClrScr;
-
- IF ParamCount > 0 THEN MBXfn := FExpand(ParamStr(1)) ELSE MBXfn := '*.MBX';
-
- EraseFile(QWKFile); { make sure we don't have one yet }
-
- FindPkZip;
-
- CreateMessageDat;
-
- Count := 0; { total messages in package }
-
- { process all the files that we find with the extension }
- FINDFIRST (MBXFn, $21, TR);
- WHILE DosError = 0 DO
- BEGIN
- NEW(FOL, Init(TR.Name, 1024));
- FOLPos := 1; { current position in RLINE array }
- GetConferenceName;
- ProcessUseNetFile (TR.Name);
- DISPOSE (FOL, Done);
- FindNext(TR);
- END;
-
- CLOSE (QwkF);
-
- CreateControlDat;
-
- Execute(PKZIP,' -ex '+QWKFile+' *.NDX MESSAGES.DAT CONTROL.DAT');
-
- CleanUp;
-
-
- END.